import json
import uuid
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.contrib.admin.views.decorators import staff_member_required
from django.contrib import messages
from django.http import HttpResponseForbidden, JsonResponse, HttpResponseNotAllowed
from django.shortcuts import get_object_or_404, redirect, render
from django.utils.translation import gettext_lazy as _
from django.db.models import Q, Count
from django.core.paginator import Paginator
from django.views.decorators.http import require_http_methods
from django.core.cache import cache
from django.utils import timezone
from datetime import timedelta

from .models import Project, ProjectMember, ProjectTag, Webhook, Announcement, Message, MessageNote, MessageProcessingHistory
from .forms import ProjectForm, ProjectMemberForm, ProjectTagForm, WebhookForm, AnnouncementForm
from accounts.models import User
from .dashboard_settings import (
    DEFAULT_MESSAGE_PAGE_SIZE,
    MAX_MESSAGES_LIMIT,
    MESSAGES_CACHE_TIMEOUT,
    STATS_CACHE_TIMEOUT,
    RECENT_MESSAGES_DAYS,
    PROJECT_LIST_LIMIT,
    ANNOUNCEMENT_LIST_LIMIT,
    PROJECT_MESSAGE_COUNT_CACHE_PREFIX,
    DASHBOARD_STATS_CACHE_KEY,
    MESSAGES_LIST_CACHE_PREFIX,
    PROJECTS_LIST_CACHE_KEY,
    ANNOUNCEMENTS_LIST_CACHE_KEY
)


@login_required
def optimized_dashboard(request):
    """优化版用户仪表盘视图 - 解决数据量大时加载缓慢的问题"""
    
    # 缓存键，使用用户ID确保缓存的用户隔离性
    cache_key = f'{DASHBOARD_STATS_CACHE_KEY}_{request.user.id}'
    cache_timeout = STATS_CACHE_TIMEOUT  # 使用配置中的缓存超时时间
    
    # 尝试从缓存中获取数据
    cached_data = cache.get(cache_key)
    
    if cached_data:
        # 如果缓存命中，直接使用缓存的数据
        context = cached_data
    else:
        # 超级管理员可以看到所有项目，普通用户只能看到自己参与的项目
        if request.user.is_super_admin():
            user_projects = Project.objects.all().order_by('-created_at')
        else:
            user_projects = Project.objects.filter(members__user=request.user).order_by('-created_at')
        
        # 获取用户在所有项目中的消息
        today = timezone.now().date()
        tomorrow = today + timedelta(days=1)
        
        # 获取所有相关项目ID
        project_ids = user_projects.values_list('id', flat=True)
        
        # 优化1: 使用select_related和prefetch_related减少数据库查询
        # 只获取最近指定天数的消息，避免加载过多历史数据
        days_ago = timezone.now() - timedelta(days=RECENT_MESSAGES_DAYS)
        
        user_messages = Message.objects.filter(
            project__in=project_ids,
            created_at__gte=days_ago  # 只获取最近指定天数的消息
        ).select_related('project', 'processed_by').order_by('-created_at')
        
        # 优化2: 使用annotate和聚合查询直接在数据库层面计算统计数据
        # 避免在Python中遍历计算
        project_stats_queryset = Project.objects.filter(id__in=project_ids).annotate(
            total_messages=Count('messages'),
            pending_messages=Count('messages', filter=Q(messages__status='pending')),
            today_messages=Count('messages', filter=Q(messages__created_at__gte=today, messages__created_at__lt=tomorrow))
        )
        
        # 转换为字典形式，方便在模板中访问
        project_stats = {}
        for project in project_stats_queryset:
            project_stats[project.id] = {
                'total_messages': project.total_messages,
                'pending_messages': project.pending_messages,
                'today_messages': project.today_messages
            }
        
        # 计算整体统计数据
        total_messages = user_messages.count()
        pending_messages = user_messages.filter(status='pending').count()
        processed_messages = total_messages - pending_messages
        today_messages = user_messages.filter(created_at__gte=today, created_at__lt=tomorrow).count()
        
        # 获取用户角色信息
        # 优化3: 批量获取所有项目成员信息，避免N+1查询
        project_roles = {}
        if request.user.is_super_admin():
            # 超级管理员对所有项目都有管理员权限
            for project in user_projects:
                project_roles[project.id] = 'admin'
        else:
            # 批量获取当前用户在所有项目中的角色
            memberships = ProjectMember.objects.filter(user=request.user, project__in=project_ids)
            for membership in memberships:
                project_roles[membership.project_id] = membership.role
        
        # 获取指定数量的公告
        announcements = Announcement.objects.filter(
            is_active=True
        ).order_by('-created_at')[:ANNOUNCEMENT_LIST_LIMIT]
        
        # 只获取最近指定数量的项目，避免在右侧显示过多项目
        recent_projects = user_projects[:PROJECT_LIST_LIMIT]
        
        # 分页处理
        # 使用配置的每页消息数量
        paginator = Paginator(user_messages, DEFAULT_MESSAGE_PAGE_SIZE)
        page_number = request.GET.get('page')
        page_obj = paginator.get_page(page_number)
        
        context = {
            'user_projects': recent_projects,  # 只显示最近的项目
            'user_messages': page_obj,
            'announcements': announcements,
            'stats': {
                'total_messages': total_messages,
                'pending_messages': pending_messages,
                'processed_messages': processed_messages,
                'today_messages': today_messages,
                'total_projects': user_projects.count()
            },
            'project_roles': project_roles,
            'page_obj': page_obj,
            'is_super_admin': request.user.is_super_admin(),
            'project_stats': project_stats
        }
        
        # 将数据存入缓存
        cache.set(cache_key, context, cache_timeout)
    
    return render(request, 'projects/optimized_dashboard.html', context)


@login_required
def api_dashboard_data(request):
    """提供仪表盘数据的API接口，用于异步加载"""
    try:
        # 超级管理员可以看到所有项目，普通用户只能看到自己参与的项目
        if request.user.is_super_admin():
            user_projects = Project.objects.all().order_by('-created_at')
        else:
            user_projects = Project.objects.filter(members__user=request.user).order_by('-created_at')
        
        # 获取所有相关项目ID
        project_ids = user_projects.values_list('id', flat=True)
        
        # 获取统计数据
        today = timezone.now().date()
        tomorrow = today + timedelta(days=1)
        
        # 只获取最近指定天数的消息
        days_ago = timezone.now() - timedelta(days=RECENT_MESSAGES_DAYS)
        
        # 统计数据
        total_messages = Message.objects.filter(
            project__in=project_ids,
            created_at__gte=days_ago
        ).count()
        
        pending_messages = Message.objects.filter(
            project__in=project_ids,
            status='pending',
            created_at__gte=days_ago
        ).count()
        
        today_messages = Message.objects.filter(
            project__in=project_ids,
            created_at__gte=today,
            created_at__lt=tomorrow
        ).count()
        
        # 项目统计数据
        project_data = []
        for project in user_projects[:PROJECT_LIST_LIMIT]:  # 只获取最近指定数量的项目数据
            project_data.append({
                'id': project.id,
                'name': project.name,
                'description': project.description,
                'message_count': project.messages.filter(created_at__gte=days_ago).count(),
                'pending_count': project.messages.filter(status='pending', created_at__gte=days_ago).count()
            })
        
        return JsonResponse({
            'success': True,
            'stats': {
                'total_messages': total_messages,
                'pending_messages': pending_messages,
                'processed_messages': total_messages - pending_messages,
                'today_messages': today_messages,
                'total_projects': user_projects.count()
            },
            'projects': project_data
        })
    except Exception as e:
        return JsonResponse({
            'success': False,
            'error': str(e)
        }, status=500)


@login_required
def api_message_list(request):
    """提供消息列表数据的API接口，用于异步加载"""
    try:
        # 获取分页参数，使用配置的默认值
        page = int(request.GET.get('page', 1))
        page_size = int(request.GET.get('page_size', DEFAULT_MESSAGE_PAGE_SIZE))
        
        # 限制页大小的最大值
        page_size = min(page_size, 100)
        
        # 超级管理员可以看到所有项目，普通用户只能看到自己参与的项目
        if request.user.is_super_admin():
            user_projects = Project.objects.all()
        else:
            user_projects = Project.objects.filter(members__user=request.user)
        
        # 获取所有相关项目ID
        project_ids = user_projects.values_list('id', flat=True)
        
        # 只获取最近指定天数的消息
        days_ago = timezone.now() - timedelta(days=RECENT_MESSAGES_DAYS)
        
        # 过滤和排序
        messages = Message.objects.filter(
            project__in=project_ids,
            created_at__gte=days_ago
        ).select_related('project', 'processed_by').order_by('-created_at')
        
        # 限制总消息数量，防止数据过多
        messages = messages[:MAX_MESSAGES_LIMIT]
        
        # 分页
        paginator = Paginator(messages, page_size)
        page_obj = paginator.get_page(page)
        
        # 构建返回数据
        message_data = []
        for msg in page_obj.object_list:
            message_data.append({
                'id': msg.id,
                'project_id': msg.project.id,
                'project_name': msg.project.name,
                'content': msg.content[:100],  # 只返回部分内容
                'message_type': msg.message_type,
                'message_type_display': msg.get_message_type_display(),
                'status': msg.status,
                'created_at': msg.created_at.strftime('%Y-%m-%d %H:%M:%S'),
                'processed_at': msg.processed_at.strftime('%Y-%m-%d %H:%M:%S') if msg.processed_at else None,
                'processed_by': msg.processed_by.username if msg.processed_by else None
            })
        
        return JsonResponse({
            'success': True,
            'messages': message_data,
            'has_next': page_obj.has_next(),
            'has_previous': page_obj.has_previous(),
            'total_pages': page_obj.paginator.num_pages,
            'current_page': page_obj.number
        })
    except Exception as e:
        return JsonResponse({
            'success': False,
            'error': str(e)
        }, status=500)


@login_required
def switch_to_optimized_dashboard(request):
    """切换到优化版仪表盘的视图"""
    messages.success(request, _('已切换到优化版仪表盘，页面加载速度将显著提升！'))
    return redirect('projects:optimized_dashboard')


# 为了方便使用，我们可以创建一个装饰器来优化其他视图

def optimized_view(timeout=60):
    """视图优化装饰器 - 添加缓存支持"""
    def decorator(view_func):
        def _wrapped_view(request, *args, **kwargs):
            # 生成基于请求路径、用户ID和GET参数的缓存键
            cache_key_parts = [
                'view',
                request.path,
                str(request.user.id) if request.user.is_authenticated else 'anonymous',
            ]
            
            # 添加GET参数到缓存键
            for key in sorted(request.GET.keys()):
                cache_key_parts.append(f'{key}={request.GET[key]}')
            
            cache_key = '_'.join(cache_key_parts)
            
            # 尝试获取缓存
            cached_response = cache.get(cache_key)
            if cached_response:
                return cached_response
            
            # 如果没有缓存，执行视图函数
            response = view_func(request, *args, **kwargs)
            
            # 缓存结果
            cache.set(cache_key, response, timeout)
            
            return response
        return _wrapped_view
    return decorator